package parsejson

import (
	"encoding/json"

	// "playbook/ginsvr/src/global"
	// "playbook/ginsvr/src/orm"
	// "playbook/ginsvr/src/utils/fileutil"
	"playbook/ginsvr/src/utils/uuidutil"
	"strings"
)

func SaveReverseJson(process Process) interface{} {
	cellsJson := reverseMain(process)
	// fmt.Println(string(cellsJson))
	var cells Cells
	json.Unmarshal(cellsJson, &cells)
	return cells
	// //写出文件
	// srcpath := orm.GetGeneSrcDefine("composejson").Srcpath

	// createDirPath := srcpath + global.PTHSEP + process.Name
	// standardName := process.Name + "_reverse.json"
	// fileutil.GetClearFile(createDirPath, standardName)

	// standardJsonPath := srcpath + global.PTHSEP + process.Name + global.PTHSEP + process.Name + "_reverse.json"
	// var strlstStandard []string
	// strlstStandard = append(strlstStandard, string(cellsJson))

	// fileutil.Filewrite(standardJsonPath, strlstStandard)

}

func reverseMain(process Process) []byte {
	var cells Cells
	var cellArray []interface{}

	startId := uuidutil.GetUUID()
	endId := uuidutil.GetUUID()
	cellArray = reverseStartCircle(process, startId, cellArray)
	cellArray = reverseEndCircle(process, endId, cellArray)
	atomIdMap := getAtomId(process)
	cellArray = reverseActivity(process, cellArray, atomIdMap, startId, endId)

	cells.Cells = cellArray
	cellsJson, _ := json.MarshalIndent(&cells, "", "\t")
	return cellsJson
}

//反解析Start-Circle
func reverseStartCircle(process Process, startId string, cellArray []interface{}) []interface{} {
	var circleStart Circle
	circleStart.Id = startId
	circleStart.Shape = "circle"
	circleStart.Data = reverseCircleData(process, "Start")
	cellArray = append(cellArray, circleStart)
	return cellArray
}

//反解析End-Circle
func reverseEndCircle(process Process, endId string, cellArray []interface{}) []interface{} {
	var circleEnd Circle
	circleEnd.Id = endId
	circleEnd.Shape = "circle"
	circleEnd.Data = reverseCircleData(process, "End")
	cellArray = append(cellArray, circleEnd)
	return cellArray
}

func reverseCircleData(process Process, cicleType string) CircleData {
	var circleData CircleData
	Start := "Start"
	End := "End"
	if cicleType == Start {
		circleData.Desc = process.Desc
		circleData.Name = process.Name
		circleData.Overtime = process.Overtime
		circleData.Version = process.Version
		circleData.Type = Start
		circleData.InputParameter = reverseInOutputParam(process.InputParameter)
	} else if cicleType == End {
		circleData.Name = End
		circleData.Type = End
		circleData.OutputParameter = reverseInOutputParam(process.OutputParameter)
	}

	return circleData
}

func reverseInOutputParam(inOutputParameter map[string]interface{}) []interface{} {
	var inOutputParameterArray []interface{}
	if inOutputParameter["parameter"] != nil {
		parameter := inOutputParameter["parameter"].(map[string]interface{})
		parameter = reverseParameter(parameter)

		//反解析parameter的data classpath
		parameterArray := parameter["parameter"].([]interface{})
		if len(parameterArray) != 0 {
			for index, value := range parameterArray {
				paramMap := value.(map[string]interface{})
				name := paramMap["name"].(string)
				if name == "data" {
					classPathArray := strings.Split(paramMap["classPath"].(string), ".")
					var classPath string
					for i := 0; i < len(classPathArray)-2; i++ {
						classPath = classPath + classPathArray[i] + "."
					}
					classPath = strings.TrimRight(classPath, ".")
					paramMap["classPath"] = classPath
				}
				parameterArray[index] = paramMap
			}
		}

		inOutputParameterArray = append(inOutputParameterArray, parameter)
	}
	return inOutputParameterArray
}

//递归修改parameter结构
func reverseParameter(parameterMap map[string]interface{}) map[string]interface{} {
	parameterType := parameterMap["type"]
	if parameterType == "List" {
		if parameterMap["parameter"] == nil {
			return parameterMap
		}
		subParam := parameterMap["parameter"].(map[string]interface{})
		var temp []interface{}
		temp = append(temp, subParam)
		parameterMap["parameter"] = temp
		reverseParameter(subParam)
	} else if parameterType == "Map" {
		if parameterMap["parameter"] == nil {
			return parameterMap
		}
		subParam := parameterMap["parameter"].([]interface{})
		for _, value := range subParam {
			subParamElement := value.(map[string]interface{})
			reverseParameter(subParamElement)
		}
	}
	return parameterMap
}

func getAtomId(process Process) map[string]string {
	atomIdMap := make(map[string]string)
	atomIdMap[process.Id] = "circle"
	if process.Activities != nil {
		activity := process.Activities
		activityArray := activity["activity"]
		for _, value := range activityArray {
			atom := value.(map[string]interface{})
			atomId := atom["id"].(string)
			atomName := atom["name"].(string)
			atomIdMap[atomId] = atomName
			if atom["type"].(float64) == 1 {
				childActivities := atom["activities"].(map[string]interface{})
				childActivityArray := childActivities["activity"].([]interface{})
				for _, childVal := range childActivityArray {
					childAtom := childVal.(map[string]interface{})
					childAtomId := childAtom["id"].(string)
					childAtomName := childAtom["name"].(string)
					atomIdMap[childAtomId] = childAtomName
				}
			}
		}
	}

	return atomIdMap
}

func reverseActivity(process Process, cellArray []interface{}, atomIdMap map[string]string, startId string, endId string) []interface{} {
	var edgeArray []interface{}
	if process.Activities != nil {
		activity := process.Activities
		activityArray := activity["activity"]
		for _, value := range activityArray {
			activityMap := value.(map[string]interface{})
			if activityMap["type"].(float64) == 1 {
				cellArray, edgeArray = reverseLoop(activityMap, atomIdMap, cellArray, startId, endId, edgeArray)
			} else {
				if activityMap["input-parameter-mapping"] != nil {
					inputParameterMapping := activityMap["input-parameter-mapping"].(map[string]interface{})
					inputMessageBeanMapping := inputParameterMapping["massage-bean-mapping"].(map[string]interface{})
					inputMessageBeanMapping = reverseInputParameterMapping(inputMessageBeanMapping, atomIdMap, startId)
					inputParameterMapping["massage-bean-mapping"] = inputMessageBeanMapping
					activityMap["input-parameter-mapping"] = inputParameterMapping
				}

				if activityMap["output-parameter-mapping"] != nil {
					outputParameterMapping := activityMap["output-parameter-mapping"].(map[string]interface{})
					outputMessageBeanMapping := outputParameterMapping["massage-bean-mapping"].(map[string]interface{})
					outputMessageBeanMapping = reverseOutputParameterMapping(outputMessageBeanMapping, atomIdMap, endId)
					outputParameterMapping["massage-bean-mapping"] = outputMessageBeanMapping
					activityMap["output-parameter-mapping"] = outputParameterMapping
				}
				edgeArray = append(edgeArray, reverseTransition(activityMap, atomIdMap, startId, endId)...)
				delete(activityMap, "transition")
				rect := make(map[string]interface{})
				rect["data"] = activityMap
				rect["id"] = activityMap["id"]
				rect["shape"] = "rect"
				cellArray = append(cellArray, rect)
			}

		}
	}
	//添加edge
	cellArray = append(cellArray, edgeArray...)
	//添加first-transition edge
	cellArray = append(cellArray, reverseFirstTransition(process.FistTransion, startId, atomIdMap, false)...)
	return cellArray
}

func reverseInputParameterMapping(messageBeanMapping map[string]interface{}, atomIdMap map[string]string, startId string) map[string]interface{} {
	mapping := messageBeanMapping["mapping"]
	mappingArray := mapping.([]interface{})
	for index, value := range mappingArray {
		mappingValue := value.(map[string]interface{})
		//from
		from := mappingValue["from"].(string)
		if from != "" {
			fromId := strings.Split(from, ".")[0]
			if atomIdMap[fromId] == "circle" {
				var fromStr string
				fromArray := strings.SplitAfter(from, ".")
				for i := 1; i < len(fromArray); i++ {
					fromStr = fromStr + fromArray[i]
				}
				fromStr = "Start." + startId + "." + fromStr
				mappingValue["from"] = fromStr
			} else {
				mappingValue["from"] = atomIdMap[fromId] + "." + from
			}
		}

		//to
		to := mappingValue["to"].(string)
		toArray := strings.SplitAfter(to, ".")
		var toStr string
		for i := 1; i < len(toArray); i++ {
			toStr = toStr + toArray[i]
		}
		mappingValue["to"] = toStr
		mappingArray[index] = mappingValue
	}
	messageBeanMapping["mapping"] = mappingArray
	return messageBeanMapping
}

func reverseOutputParameterMapping(messageBeanMapping map[string]interface{}, atomIdMap map[string]string, endId string) map[string]interface{} {
	mapping := messageBeanMapping["mapping"]
	mappingArray := mapping.([]interface{})
	for index, value := range mappingArray {
		mappingValue := value.(map[string]interface{})
		//to
		to := mappingValue["to"].(string)
		if to != "" {
			toId := strings.Split(to, ".")[0]
			if atomIdMap[toId] == "circle" {
				var toStr string
				toArray := strings.SplitAfter(to, ".")
				for i := 1; i < len(toArray); i++ {
					toStr = toStr + toArray[i]
				}
				toStr = "End." + endId + "." + toStr
				mappingValue["to"] = toStr
			} else {
				mappingValue["to"] = atomIdMap[toId] + "." + to
			}
		}

		//from
		from := mappingValue["from"].(string)
		fromArray := strings.SplitAfter(from, ".")
		var fromStr string
		for i := 1; i < len(fromArray); i++ {
			fromStr = fromStr + fromArray[i]
		}

		mappingValue["from"] = fromStr
		mappingArray[index] = mappingValue
	}
	messageBeanMapping["mapping"] = mappingArray

	return messageBeanMapping
}

func reverseTransition(activity map[string]interface{}, atomIdMap map[string]string, startId string, endId string) []interface{} {
	var edgeArray []interface{}
	sourceId := activity["id"].(string)
	if activity["transition"] != nil {
		transitionArray := activity["transition"].([]interface{})
		for _, value := range transitionArray {
			edge := make(map[string]interface{})
			source := make(map[string]interface{})
			target := make(map[string]interface{})

			transition := value.(map[string]interface{})
			targetId := transition["activityId"].(string)
			source["cell"] = sourceId
			target["cell"] = targetId
			edge["source"] = source
			edge["target"] = target
			edge["id"] = uuidutil.GetUUID()
			edge["shape"] = "edge"
			if transition["activityName"] != nil {
				transition = reverseTransitionLeftContent(transition, atomIdMap)
				edge["data"] = transition
			}
			edgeArray = append(edgeArray, edge)
		}
	}
	if activity["transition"] == nil && activity["loopFlag"] == nil {
		edge := make(map[string]interface{})
		source := make(map[string]interface{})
		target := make(map[string]interface{})
		source["cell"] = sourceId
		target["cell"] = endId
		edge["source"] = source
		edge["target"] = target
		edge["id"] = uuidutil.GetUUID()
		edge["shape"] = "edge"
		edgeArray = append(edgeArray, edge)
	}

	return edgeArray
}

func reverseTransitionLeftContent(transition map[string]interface{}, atomIdMap map[string]string) map[string]interface{} {
	expression := transition["expression"].(map[string]interface{})
	rootNode := expression["rootNode"].(map[string]interface{})
	children := rootNode["children"].([]interface{})
	childrenMap := children[0].(map[string]interface{})
	childrenMap = reverseLeftContent(childrenMap, atomIdMap)

	exetraRulesArray := childrenMap["extraRules"].([]interface{})
	for index, value := range exetraRulesArray {
		exetraRules := value.(map[string]interface{})
		exetraRules = reverseLeftContent(exetraRules, atomIdMap)
		exetraRulesArray[index] = exetraRules
	}
	childrenMap["extraRules"] = exetraRulesArray
	children[0] = childrenMap
	rootNode["children"] = children
	expression["rootNode"] = rootNode
	transition["expression"] = expression
	return transition
}

func reverseLeftContent(node map[string]interface{}, atomIdMap map[string]string) map[string]interface{} {
	leftContent := node["leftContent"].(string)
	leftContentArray := strings.SplitAfter(leftContent, ".")
	var strLeftContent string
	for index, value := range leftContentArray {
		if index == 0 {
			atomId := strings.Trim(leftContentArray[index], ".")
			strLeftContent = atomIdMap[atomId] + "." + atomId + "."
		}
		if index > 0 {
			strLeftContent = strLeftContent + value
		}
	}
	node["leftContent"] = strLeftContent
	return node
}

func reverseFirstTransition(firstTransition []interface{}, sourceId string, atomIdMap map[string]string, isLoop bool) []interface{} {
	var edgeArray []interface{}
	for _, value := range firstTransition {
		edge := make(map[string]interface{})
		source := make(map[string]interface{})
		target := make(map[string]interface{})

		transition := value.(map[string]interface{})
		targetId := transition["activityId"].(string)
		source["cell"] = sourceId
		target["cell"] = targetId
		edge["source"] = source
		edge["target"] = target
		edge["id"] = uuidutil.GetUUID()
		if isLoop {
			edge["parent"] = sourceId
		}
		edge["shape"] = "edge"
		if transition["activityName"] != nil {
			transition = reverseTransitionLeftContent(transition, atomIdMap)
			edge["data"] = transition
		}
		edgeArray = append(edgeArray, edge)
	}
	return edgeArray
}

func reverseLoop(activitiy map[string]interface{}, atomIdMap map[string]string, cellArray []interface{}, startId string, endId string,
	edgeArray []interface{}) ([]interface{}, []interface{}) {
	parentId := activitiy["id"].(string)
	childActivities := activitiy["activities"].(map[string]interface{})
	childActivityArray := childActivities["activity"].([]interface{})
	var children []interface{}
	for _, value := range childActivityArray {
		childActivity := value.(map[string]interface{})
		children = append(children, childActivity["id"])
		if childActivity["input-parameter-mapping"] != nil {
			inputParameterMapping := childActivity["input-parameter-mapping"].(map[string]interface{})
			inputMessageBeanMapping := inputParameterMapping["massage-bean-mapping"].(map[string]interface{})
			inputMessageBeanMapping = reverseInputParameterMapping(inputMessageBeanMapping, atomIdMap, startId)
			inputParameterMapping["massage-bean-mapping"] = inputMessageBeanMapping
			childActivity["input-parameter-mapping"] = inputParameterMapping
		}

		if childActivity["output-parameter-mapping"] != nil {
			outputParameterMapping := childActivity["output-parameter-mapping"].(map[string]interface{})
			outputMessageBeanMapping := outputParameterMapping["massage-bean-mapping"].(map[string]interface{})
			outputMessageBeanMapping = reverseOutputParameterMapping(outputMessageBeanMapping, atomIdMap, endId)
			outputParameterMapping["massage-bean-mapping"] = outputMessageBeanMapping
			childActivity["output-parameter-mapping"] = outputParameterMapping
		}
		childEdges := reverseTransition(childActivity, atomIdMap, startId, endId)
		for index, val := range childEdges {
			edge := val.(map[string]interface{})
			edge["parent"] = parentId
			edgeId := edge["id"].(string)
			children = append(children, edgeId)
			childEdges[index] = edge
		}
		edgeArray = append(edgeArray, childEdges...)
		delete(childActivity, "transition")
		rect := make(map[string]interface{})
		rect["data"] = childActivity
		rect["id"] = childActivity["id"]
		rect["parent"] = parentId
		rect["shape"] = "rect"
		cellArray = append(cellArray, rect)
	}
	if activitiy["input-parameter-mapping"] != nil {
		inputParameterMapping := activitiy["input-parameter-mapping"].(map[string]interface{})
		inputMessageBeanMapping := inputParameterMapping["massage-bean-mapping"].(map[string]interface{})
		inputMessageBeanMapping = reverseInputParameterMapping(inputMessageBeanMapping, atomIdMap, startId)
		inputParameterMapping["massage-bean-mapping"] = inputMessageBeanMapping
		activitiy["input-parameter-mapping"] = inputParameterMapping
	}

	if activitiy["loop-input-parameter-mapping"] != nil {
		inputParameterMapping := activitiy["loop-input-parameter-mapping"].(map[string]interface{})
		inputMessageBeanMapping := inputParameterMapping["massage-bean-mapping"].(map[string]interface{})
		inputMessageBeanMapping = reverseInputParameterMapping(inputMessageBeanMapping, atomIdMap, startId)
		inputParameterMapping["massage-bean-mapping"] = inputMessageBeanMapping
		activitiy["loop-input-parameter-mapping"] = inputParameterMapping
	}

	if activitiy["loop-output-parameter-mapping"] != nil {
		outputParameterMapping := activitiy["loop-output-parameter-mapping"].(map[string]interface{})
		outputMessageBeanMapping := outputParameterMapping["massage-bean-mapping"].(map[string]interface{})
		outputMessageBeanMapping = reverseOutputParameterMapping(outputMessageBeanMapping, atomIdMap, endId)
		outputParameterMapping["massage-bean-mapping"] = outputMessageBeanMapping
		activitiy["loop-output-parameter-mapping"] = outputParameterMapping
	}
	edgeArray = append(edgeArray, reverseTransition(activitiy, atomIdMap, startId, endId)...)

	//处理loop-first-transition
	firstTransition := activitiy["first-transition"].([]interface{})
	firstEdges := reverseFirstTransition(firstTransition, parentId, atomIdMap, true)
	for _, val := range firstEdges {
		edge := val.(map[string]interface{})
		edgeId := edge["id"].(string)
		children = append(children, edgeId)
	}
	edgeArray = append(edgeArray, reverseFirstTransition(firstTransition, parentId, atomIdMap, true)...)

	delete(activitiy, "transition")
	delete(activitiy, "first-transition")
	delete(activitiy, "activities")
	rect := make(map[string]interface{})
	rect["data"] = activitiy
	rect["id"] = activitiy["id"]
	rect["children"] = children
	rect["shape"] = "rect"

	cellArray = append(cellArray, rect)
	return cellArray, edgeArray
}
